home *** CD-ROM | disk | FTP | other *** search
/ Deutsche Edition 1 / Deutsche Edition 1.iso / amok / amok_lha / amok24.lha / DME / SRC / source.zoo / command.c < prev    next >
C/C++ Source or Header  |  1989-07-03  |  22KB  |  711 lines

  1.  
  2. /*
  3.  * COMMAND.C
  4.  *
  5.  *      (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  *
  7.  * )c                single character (typing)
  8.  * 'c                single character (typing)
  9.  * `string'          string of characters w/ embedded `' allowed!
  10.  * (string)             same thing w/ embedded () allowed!
  11.  * \c                override
  12.  *
  13.  * name arg arg      command name. The arguments are interpreted as strings
  14.  *                   for the command.
  15.  *
  16.  * $scanf            macro insert scanf'd variable
  17.  * $filename         macro insert current file name
  18.  *
  19.  * Any string arguments not part of a command are considered to be typed
  20.  * text.
  21.  */
  22.  
  23. #include "defs.h"
  24. #include <stdio.h>
  25.  
  26. #if AREXX
  27. extern int foundcmd;       /* control for implicit ARexx macro invocation   */
  28. extern int cmderr;         /* global command error flag for do_rexx()'s use */
  29. #endif
  30.  
  31. #define CF_COK  1   /*  Can be executed while in command line mode      */
  32. #define CF_PAR  2   /*  ESCIMM special flag.. save rest of command line */
  33.                     /*  so it can be executed after user entry          */
  34.  
  35. #define CF_ICO  4   /*  OK to execute if iconified, else uniconify first*/
  36.  
  37. extern char *breakout();
  38. extern PROC *proc;
  39.  
  40. typedef struct {
  41.    char *name;      /* command name       */
  42.    ubyte args;
  43.    ubyte flags;
  44.    int (*func)();   /* function           */
  45. } COMM;
  46.  
  47. extern int  do_map(),       do_unmap(),     do_up(),        do_down(),
  48.             do_left(),      do_right(),     do_return(),    do_bs(),
  49.             do_del(),       do_esc(),       do_downadd(),   do_lastcolumn(),
  50.             do_firstcolumn(),do_edit(),     do_tab(),       do_backtab(),
  51.             do_save(),      do_saveas(),    do_deline(),    do_insline(),
  52.             do_top(),       do_bottom(),    do_source(),    do_firstnb(),
  53.             do_quit(),      do_find(),      do_page(),      do_savetabs(),
  54.             do_split(),     do_goto(),      do_screentop(), do_screenbottom(),
  55.             do_join(),      do_repeat(),    do_tabstop(),   do_insertmode(),
  56.             do_block(),     do_bdelete(),   do_bcopy(),     do_bmove(),
  57.             do_bsave(),     do_wleft(),     do_wright(),    do_remeol(),
  58.             do_savemap(),   do_toggle(),    do_if(),        do_tlate(),
  59.             do_bsource(),   do_findr(),     do_findstr(),   do_newwindow(),
  60.             do_windowparm(),do_resize(),    do_margin(),    do_wordwrap(),
  61.             do_reformat(),  do_execute(),   do_chfilename(),do_scrollup(),
  62.             do_scrolldown(),do_recall(),    do_scanf(),     do_iconify(),
  63.             do_tomouse(),   do_abort(),     do_arpload(),   do_arpsave(),
  64.             do_arpinsfile(),do_setfont(),   do_ignorecase(),do_multireplace(),
  65.             do_addpath(),   do_rempath(),   do_set(),       do_setenv(),
  66.             do_unset(),     do_unsetenv(),  do_ipc(),       do_cd(),
  67.             do_undeline();
  68.  
  69. #ifndef NO_DO_REF
  70. extern int  do_refs();
  71. #endif
  72.  
  73. #ifndef NO_DO_CTAGS
  74. extern int  do_ctags();
  75. #endif
  76.  
  77. extern int  do_menu(), do_menuclear(), do_menuadd(), do_menudel(),
  78.             do_menudelhdr(), do_menuon(), do_menuoff();
  79.  
  80. extern int  do_null(), do_rx();
  81.  
  82. extern int  do_pushmark(),  do_popmark(),   do_swapmark(),  do_purgemark(),
  83.             do_ping(),      do_pong(),      do_undo();
  84.  
  85. #if AREXX
  86. extern int  do_rx(),        do_rx1(),       do_rx2();
  87. #endif
  88.  
  89. #if M2ERR
  90. extern int  do_firsterr(),  do_nexterr(), do_preverr(), do_currenterr();
  91. #endif
  92.  
  93. /*============================================================================*/
  94.  
  95. /*
  96.  *  WLEFT/WRIGHT will check command line mode themselves, and thus can
  97.  *  be marked flags=1 even though they can change the line number.
  98.  *
  99.  *  No more than 255 commands may exist unless you change the type of hindex[]
  100.  *
  101.  *  Command names MUST be sorted by their first character
  102.  */
  103.  
  104. unsigned char hindex[26];   /*  alpha hash into table   */
  105.  
  106.         /*        args flags    */
  107.  
  108. COMM Comm[] = {
  109.     "abort",         0,     0,  do_abort,
  110. #ifndef NO_DO2
  111.     "addpath",       1, CF_COK, do_addpath,
  112. #endif
  113.     "arpinsfile",    0,      0, do_arpinsfile,
  114.     "arpload",       0,      0, do_arpload,
  115.     "arpsave",       0,      0, do_arpsave,
  116.     "back",          0, CF_COK, do_bs,
  117.     "backtab",       0, CF_COK, do_backtab,
  118.     "bcopy",         0,      0, do_bcopy,
  119.     "bdelete",       0,      0, do_bdelete,
  120.     "block",         0,      0, do_block,    /* checks com name for mode */
  121.     "bmove",         0,      0, do_bmove,
  122.     "bottom",        0,      0, do_bottom,
  123.     "bs",            0, CF_COK, do_bs,
  124.     "bsave",         1, CF_COK, do_bsave,
  125.     "bsource",       0,      0, do_bsource,
  126.     "cd",            1, CF_COK, do_cd,
  127.     "chfilename",    1,      0, do_chfilename,
  128. #ifndef NO_DO_CTAGS
  129.     "ctags",         0, CF_ICO, do_ctags,
  130. #endif
  131. #if M2ERR
  132.     "currenterr",    0, CF_COK, do_currenterr,
  133. #endif
  134.     "del",           0, CF_COK, do_del,
  135.     "deline",        0,      0, do_deline,
  136.     "down",          0,      0, do_down,
  137.     "downadd",       0,      0, do_downadd,
  138.     "esc",           0, CF_COK, do_esc,
  139.     "escimm",        1, CF_PAR, do_esc,
  140.     "execute",       1, CF_ICO, do_execute,
  141.     "find",          1,      0, do_find,     /* checks com name for mode */
  142.     "findr",         2,      0, do_findr,    /* checks com name for mode */
  143.     "findstr",       1, CF_COK, do_findstr,  /* checks com name for mode */
  144.     "first",         0, CF_COK, do_firstcolumn,
  145. #if M2ERR
  146.     "firsterr",      0, CF_COK, do_firsterr,
  147. #endif
  148.     "firstnb",       0, CF_COK, do_firstnb,
  149.     "goto",          1,      0, do_goto,
  150.     "height",        1, CF_COK, do_windowparm,
  151.     "iconify",       0, CF_ICO, do_iconify,
  152.     "if",            2, CF_COK, do_if,
  153.     "ifelse",        3, CF_COK, do_if,
  154.     "ignorecase",    1, CF_COK, do_ignorecase,
  155.     "insertmode",    1, CF_COK, do_insertmode,
  156.     "insfile",       1,      0, do_edit,
  157.     "insline",       0,      0, do_insline,
  158.     "ipc",           3, CF_COK, do_ipc,
  159.     "join",          0,      0, do_join,
  160.     "last",          0, CF_COK, do_lastcolumn,
  161.     "left",          0, CF_COK, do_left,
  162.     "leftedge",      1, CF_COK, do_windowparm,
  163.     "map",           2, CF_COK, do_map,
  164.     "margin",        1, CF_COK, do_margin,
  165.     "menuadd",       3,      0, do_menuadd,
  166.     "menudel",       2,      0, do_menudel,
  167.     "menudelhdr",    1,      0, do_menudelhdr,
  168.     "menuclear",     0,      0, do_menuclear,
  169.     "menuon",        0,      0, do_menuon,
  170.     "menuoff",       0,      0, do_menuoff,
  171.     "multireplace",  2,      0, do_multireplace,
  172.     "newfile",       1,      0, do_edit,     /* checks com name for mode */
  173.     "newwindow",     0, CF_ICO, do_newwindow,
  174.     "next",          0,      0, do_find,
  175. #if M2ERR
  176.     "nexterr",       0, CF_COK, do_nexterr,
  177. #endif
  178.     "nextr",         0,      0, do_findr,
  179.     "null",          0, CF_COK, do_null,
  180.     "pagedown",      0,      0, do_page,
  181.     "pageset",       1,      0, do_page,
  182.     "pageup",        0,      0, do_page,
  183.     "ping",          1, CF_ICO, do_ping,
  184.     "pong",          1,      0, do_pong,
  185.     "prev",          0,      0, do_find,
  186. #if M2ERR
  187.     "preverr",       0, CF_COK, do_preverr,
  188. #endif
  189.     "prevr",         0,      0, do_findr,
  190.     "popmark",       0,      0, do_popmark,
  191.     "purgemark",     0,      0, do_purgemark,
  192.     "pushmark",      0,      0, do_pushmark,
  193.     "quit",          0, CF_ICO, do_quit,
  194.     "recall",        0, CF_COK, do_recall,
  195. #ifndef NO_DO_REF
  196.     "ref",           0,      0, do_refs,
  197. #endif
  198.     "reformat",      0,      0, do_reformat,
  199.     "remeol",        0, CF_COK, do_remeol,
  200. #ifndef NO_DO2
  201.     "rempath",       1, CF_COK, do_rempath,
  202. #endif
  203.     "repeat",        2, CF_ICO|CF_COK, do_repeat,
  204.     "repstr",        1, CF_COK, do_findstr,
  205.     "resettoggle",   1, CF_COK, do_toggle,
  206.     "resize",        2,      0, do_resize,
  207.     "return",        0, CF_COK, do_return,   /* special meaning in command line mode */
  208.     "right",         0, CF_COK, do_right,
  209. #if AREXX
  210.     "rx",            1,      0, do_rx,       /* explicit ARexx macro invocation      */
  211.     "rx1",           2,      0, do_rx1,      /* explicit, with 1 arg  to ARexx macro */
  212.     "rx2",           3,      0, do_rx2,      /* explicit, with 2 args to ARexx macro */
  213. #endif
  214.     "saveas",        1, CF_ICO|CF_COK, do_saveas,
  215.     "savemap",       1, CF_ICO|CF_COK, do_savemap,  /* checks com name for mode */
  216.     "saveold",       0, CF_ICO|CF_COK, do_save,
  217.     "savesmap",      1, CF_ICO|CF_COK, do_savemap,
  218.     "savetabs",      1, CF_ICO|CF_COK, do_savetabs,
  219.     "scanf",         1, CF_COK, do_scanf,
  220.     "screenbottom",  0,      0, do_screenbottom,
  221.     "screentop",     0,      0, do_screentop,
  222.     "scrollup",      0,      0, do_scrollup,
  223.     "scrolldown",    0,      0, do_scrolldown,
  224.     "set",           2, CF_ICO|CF_COK, do_set,
  225.     "setenv",        2, CF_ICO|CF_COK, do_setenv,
  226.     "setfont",       2,      0, do_setfont,
  227.     "settoggle",     1, CF_COK, do_toggle,
  228.     "source",        1, CF_COK, do_source,
  229.     "split",         0,      0, do_split,
  230.     "swapmark",      0,      0, do_swapmark,
  231.     "tab",           0, CF_COK, do_tab,
  232.     "tabstop",       1, CF_COK, do_tabstop,
  233.     "tlate",         1, CF_COK, do_tlate,
  234.     "tmpheight",     1, CF_COK, do_windowparm,
  235.     "tmpwidth",      1, CF_COK, do_windowparm,
  236.     "toggle",        1, CF_COK, do_toggle,
  237.     "tomouse",       0,      0, do_tomouse,
  238.     "top",           0,      0, do_top,
  239.     "topedge",       1, CF_COK, do_windowparm,
  240.     "unblock",       0,      0, do_block,
  241.     "undeline",      0,      0, do_undeline,
  242.     "undo",          0,      0, do_undo,
  243.     "unmap",         1, CF_ICO|CF_COK, do_unmap,
  244.     "unset",         1, CF_ICO|CF_COK, do_unset,
  245.     "unsetenv",      1, CF_ICO|CF_COK, do_unsetenv,
  246.     "up",            0,      0, do_up,
  247.     "while",         2, CF_ICO|CF_COK, do_if,
  248.     "width",         1, CF_COK, do_windowparm,
  249.     "wleft",         0, CF_COK, do_wleft,
  250.     "wordwrap",      1, CF_COK, do_wordwrap,
  251.     "wright",        0, CF_COK, do_wright,
  252.     NULL, 0, 0, NULL
  253. };
  254.  
  255. init_command()
  256. {
  257.     register short hi;
  258.     register COMM *comm;
  259.  
  260.     hi = sizeof(Comm)/sizeof(Comm[0]) - 2;
  261.     comm = Comm + hi;
  262.  
  263.     while (hi >= 0) {
  264.         hindex[comm->name[0] - 'a'] = hi;
  265.         --hi;
  266.         --comm;
  267.     }
  268. }
  269.  
  270. #define MAXIA   5
  271.  
  272. do_command(str)
  273. char *str;
  274. {
  275.     register char *arg;
  276.     char *aux1, *aux2;
  277.     char *repstr[MAXIA];
  278.     char quoted;
  279.     short repi = 0;
  280.     register short i, j;
  281.     static int level;
  282.  
  283.     if (++level > (proc->pr_StackSize-625) / 17 ) {
  284.         title("Recursion Too Deep!");
  285.         --level;
  286. #if AREXX
  287.         foundcmd = 1;   /* to prevent us from trying an ARexx macro */
  288. #endif
  289.         return(0);
  290.     }
  291.  
  292.     while (arg = breakout(&str, "ed, &aux1)) {
  293.         if(breakcheck())
  294.             goto fail;
  295.         if (quoted) {
  296.             if (Ep->iconmode)
  297.                 uniconify();
  298.             text_write(arg);
  299.             goto loop;
  300.         }
  301.         for (i = 0; arg[i]; ++i) {
  302.             if (arg[i] >= 'A' && arg[i] <= 'Z')
  303.                 arg[i] += 'a' - 'A';
  304.         }
  305.  
  306.         if (arg[0] >= 'a' && arg[0] <= 'z') {
  307.             register COMM *comm = &Comm[hindex[arg[0]-'a']];
  308.             for (; comm->name && comm->name[0] == arg[0]; ++comm) {
  309.                 if (strcmp(arg, comm->name) == 0) {
  310. #if AREXX
  311.                     foundcmd = 1;
  312. #endif
  313.                     av[0] = (ubyte *)comm->name;
  314.                     for (j = 1; j <= comm->args; ++j) {
  315.                         av[j] = (ubyte *)breakout(&str, "ed, &aux2);
  316.                         if (aux2) {
  317.                             if (repi == MAXIA) {
  318.                                 free(aux2);
  319.                                 title("Command too complex");
  320.                                 goto fail;
  321.                             } else {
  322.                                 repstr[repi++] = aux2;
  323.                             }
  324.                         }
  325.                         if (!av[j]) {
  326.                             title("Bad argument");
  327.                             goto fail;
  328.                         }
  329.                     }
  330.                     av[j] = NULL;   /* end of arglist */
  331.                     if ((comm->flags & CF_COK) || !Comlinemode) {
  332.                         if (comm->flags & CF_PAR) {
  333.                             if (Partial)
  334.                                 free(Partial);
  335.                             Partial = (char *)malloc(strlen(str)+1);
  336.                             strcpy(Partial, str);
  337.                             str += strlen(str);     /*  skip string */
  338.                         }
  339.                         if (Ep->iconmode && !(comm->flags & CF_ICO))
  340.                             uniconify();
  341.                         (*comm->func)(-1);
  342.                     }
  343.                     if (Abortcommand)
  344.                         goto fail;
  345.                     goto loop;
  346.                 }
  347.             }
  348.         }
  349.  
  350.         /* Command not found, check for macro   */
  351.  
  352.         {
  353.             char *str;
  354.             int ret;
  355.             if ((str = keyspectomacro(arg)) || (str = menutomacro(arg))) {
  356.                 str = (char *)strcpy(malloc(strlen(str)+1), str);
  357.                 ret = do_command(str);
  358.                 free(str);
  359. #if AREXX
  360.                 if (ret) {
  361.                     foundcmd = 1;   /* dunno about this yet for ARexx macros */
  362.                     goto loop;
  363.                 }
  364. #else
  365.                 if (ret)
  366.                     goto loop;
  367. #endif
  368.                 goto fail;
  369.             }
  370.         }
  371.  
  372.         /* Command still not found, check for public macro  */
  373.         /* code to be added */
  374.  
  375. #if AREXX
  376.         do_rxImplied(arg, str);
  377. #else
  378.         title("Unknown Command");
  379. #endif
  380. fail:
  381.         --level;
  382.         while (--repi >= 0)
  383.             free(repstr[repi]);
  384.         if (aux1)
  385.             free(aux1);
  386.         return(0);
  387. loop:
  388.         if (aux1)
  389.             free(aux1);
  390.     }
  391.     --level;
  392.     while (--repi >= 0)
  393.         free(repstr[repi]);
  394.     return(1);
  395. }
  396.  
  397. do_null()
  398. {
  399. }
  400.  
  401. do_source()
  402. {
  403.     char buf[256];
  404.     long xfi;
  405.     register char *str;
  406.     long oldlock = CurrentDir(DupLock(Ep->dirlock));
  407.  
  408.     proc->pr_WindowPtr = (APTR) Ep->Win;
  409.     if (xfi = xfopen(av[1], "r", 512)) {
  410.         while (xfgets(xfi, buf, 256) >= 0) {
  411.             if (buf[0] == '#')
  412.                 continue;
  413.             for (str = buf; *str; ++str) {
  414.                 if (*str == 9)
  415.                     *str = ' ';
  416.             }
  417.             do_command(buf);
  418.         }
  419.         xfclose(xfi);
  420.     } else {
  421.         if (av[0])
  422.             title("File not found");
  423.     }
  424.     UnLock(CurrentDir(oldlock));
  425. }
  426.  
  427.  
  428. do_quit()
  429. {
  430.     extern char Quitflag;
  431.  
  432.     Quitflag = 1;
  433. }
  434.  
  435. do_execute()
  436. {
  437.     long oldlock = CurrentDir(Ep->dirlock);
  438.  
  439.     Execute(av[1], NULL, NULL);
  440.     CurrentDir(oldlock);
  441. }
  442.  
  443. /*
  444.  * repeat X command
  445.  *
  446.  * Since repeat takes up 512+ stack, it should not be nested more than
  447.  * twice.
  448.  *
  449.  * (if X is not a number it can be abbr. with 2 chars)
  450.  *
  451.  * X =  N     -number of repeats
  452.  *      line  -current line # (lines begin at 1)
  453.  *      lbot  -#lines to the bottom, inc. current
  454.  *      cleft -column # (columns begin at 0)
  455.  *              (thus is also chars to the left)
  456.  *      cright-#chars to eol, including current char
  457.  *      tr    -#char positions to get to next tab stop
  458.  *      tl    -#char positions to get to next backtab stop
  459.  */
  460.  
  461. #define SC(a,b) ((a)<<8|(b))
  462.  
  463. do_repeat()
  464. {
  465.     register ubyte *ptr = av[1];
  466.     register unsigned long n;
  467.     char buf1[256];
  468.     char buf2[256];
  469.  
  470.     breakreset();
  471.     strcpy(buf1, av[2]);
  472.     switch((ptr[0]<<8)+ptr[1]) {
  473.     case SC('l','i'):
  474.         n = text_lineno();
  475.         break;
  476.     case SC('l','b'):
  477.         n = text_lines() - text_lineno() + 1;
  478.         break;
  479.     case SC('c','l'):
  480.         n = text_colno();
  481.         break;
  482.     case SC('c','r'):
  483.         n = text_cols() - text_colno();
  484.         break;
  485.     case SC('t','r'):
  486.         n = text_tabsize()-(text_colno() % text_tabsize());
  487.         break;
  488.     case SC('t','l'):
  489.         n = text_colno() % text_tabsize();
  490.         if (n == 0)
  491.             n = text_tabsize();
  492.         break;
  493.     default:
  494.         n = atoi(av[1]);
  495.         break;
  496.     }
  497.     while (n > 0) {
  498.         strcpy(buf2, buf1);
  499.         if (do_command(buf2) == 0 || breakcheck()) {
  500.             Abortcommand = 1;
  501.             break;
  502.         }
  503.         --n;
  504.     }
  505. }
  506.  
  507. /*
  508.  *  BREAKOUT()
  509.  *
  510.  *  Break out the next argument.  The argument is space delimited and
  511.  *  might be quoted with `' or (), or single quoted as 'c or )c
  512.  *
  513.  *  Also:       $var        -variable insertion
  514.  *              ^c          -control character
  515.  */
  516.  
  517. char *
  518. breakout(ptr, quoted, paux)
  519. register char **ptr;
  520. char **paux;
  521. char *quoted;
  522. {
  523.     register char *str = *ptr;
  524.     char *base;
  525.     short count = 0;
  526.     char opc = 0;
  527.     char clc = 0;
  528.     char immode = 0;
  529.     char isaux = 0;
  530.     char buf[256];
  531.     short di = 0;
  532.  
  533.     *quoted = 0;
  534.     *paux = NULL;
  535.     while (*str == ' ')
  536.         ++str;
  537.     if (!*str)
  538.         return(NULL);
  539.  
  540.     *ptr = str;
  541.     base = str;
  542.     while (*str) {
  543.         if (immode) {
  544.             if (di != sizeof(buf)-1)
  545.                 buf[di++] = *str;
  546.             ++str;
  547.             continue;
  548.         }
  549.         if (count == 0) {
  550.             if (*str == ' ')
  551.                 break;
  552.             if (*str == '\'' || *str == ')')
  553.                 clc = *str;
  554.             if (*str == '`') {
  555.                 opc = '`';
  556.                 clc = '\'';
  557.             }
  558.             if (*str == '(') {
  559.                 opc = '(';
  560.                 clc = ')';
  561.             }
  562.         }
  563.         if (*str == opc) {
  564.             ++count;
  565.             if (str == *ptr) {
  566.                 *quoted = 1;
  567.                 base = ++str;
  568.                 continue;
  569.             }
  570.         }
  571.         if (*str == clc) {
  572.             --count;
  573.             if (count == 0 && *quoted)     /*  end of argument     */
  574.                 break;
  575.             if (str == *ptr && count < 0) {
  576.                 immode = 1;
  577.                 *quoted = 1;
  578.                 base = ++str;
  579.                 continue;
  580.             }
  581.         }
  582.  
  583.         /*
  584.          *  $varname $(varname) $`varname'.  I.E. three forms are allowed,
  585.          *  which allows one to insert the string almost anywhere.  The
  586.          *  first form names are limited to alpha-numerics, '-', and '_'.
  587.          */
  588.  
  589.         if (*str == '$') {
  590.             register char *ptr;
  591.             char c, ce;
  592.             short len;
  593.  
  594.             ce = 0;                         /*  first form  */
  595.             ++str;                          /*  skip $      */
  596.             if (*str == '(') {              /*  second form */
  597.                 ce = ')';
  598.                 ++str;
  599.             } else if (*str == '`') {       /*  third form  */
  600.                 ce = '\'';
  601.                 ++str;
  602.             }
  603.             ptr = str;                      /*  start of varname    */
  604.             if (ce) {                       /*  until end char OR   */
  605.                 while (*ptr && *ptr != ce)
  606.                     ++ptr;
  607.             } else {                        /*  smart end-varname   */
  608.                 while ((*ptr >= 'a' && *ptr <= 'z') ||
  609.                         (*ptr >= 'A' && *ptr <= 'Z') ||
  610.                         (*ptr >= '0' && *ptr <= '9') ||
  611.                         *ptr == '-' || *ptr == '_' ) {
  612.                     ++ptr;
  613.                 }
  614.             }
  615.             len = ptr - str;                /*  length of variable  */
  616.  
  617.             c = *ptr; *ptr = 0;             /*  temp. terminate \0  */
  618.             if (strcmp(str, "scanf") == 0) {
  619.                 *ptr = c;
  620.                 isaux = 1;
  621.                 if (di + strlen(String) < sizeof(buf)-1) {
  622.                     strcpy(buf + di, String);
  623.                     di += strlen(buf + di);
  624.                 }
  625.                 str += len;                 /*  next string pos     */
  626.                 if (ce)
  627.                     ++str;
  628.                 continue;
  629.             }
  630.             if (strcmp(str, "filename") == 0) {
  631.                 *ptr = c;
  632.                 isaux = 1;
  633.                 if (di + strlen(Ep->Name) < sizeof(buf)-1) {
  634.                     strcpy(buf + di, Ep->Name);
  635.                     di += strlen(buf + di);
  636.                 }
  637.                 str += len;
  638.                 if (ce)
  639.                     ++str;
  640.                 continue;
  641.             }
  642.             if (strcmp(str, "colno") == 0) {
  643.                 *ptr = c;
  644.                 isaux = 1;
  645.                 if (di < sizeof(buf)-8) {
  646.                     sprintf(buf + di, "%ld", Ep->Column + 1);
  647.                     di += strlen(buf + di);
  648.                 }
  649.                 str += len;
  650.                 if (ce)
  651.                     ++str;
  652.                 continue;
  653.             }
  654.             if (strcmp(str, "lineno") == 0) {
  655.                 *ptr = c;
  656.                 isaux = 1;
  657.                 if (di < sizeof(buf)-8) {
  658.                     sprintf(buf + di, "%ld", Ep->Line + 1);
  659.                     di += strlen(buf + di);
  660.                 }
  661.                 str += len;
  662.                 if (ce)
  663.                     ++str;
  664.                 continue;
  665.             }
  666.             if (ptr = getvar(str)) {
  667.                 str[len] = c;
  668.                 isaux = 1;
  669.                 if (di + strlen(ptr) < sizeof(buf)-1) {
  670.                     strcpy(buf + di, ptr);
  671.                     di += strlen(buf + di);
  672.                 }
  673.                 str += len;
  674.                 if (ce)
  675.                     ++str;
  676.                 free(ptr);
  677.                 continue;
  678.             }
  679.             *ptr = c;
  680.             --str;
  681.             if (ce)
  682.                 --str;
  683.         }
  684.         if (*str == '^' && (str[1] & 0x1F)) {
  685.             ++str;
  686.             *str &= 0x1F;
  687.             isaux = 1;
  688.         }
  689.         if (*str == '\\' && str[1]) {
  690.             ++str;
  691.             isaux = 1;
  692.         }
  693.         buf[di++] = *str++;
  694.     }
  695.     buf[di++] = 0;
  696.     if (isaux) {
  697.         *paux = malloc(di);
  698.         strcpy(*paux, buf);
  699.         base = *paux;
  700.     }
  701.     if (*str) {             /*  space ended */
  702.         *str = '\0';
  703.         *ptr = str + 1;     /*  next arg    */
  704.     } else {
  705.         *ptr = str;         /*  last arg    */
  706.     }
  707.     return(base);
  708. }
  709.  
  710.  
  711.